#ifndef BOOST_NUMERIC_QUADRATURE_KRONROD_COEFFICIENTS_HPP
#define BOOST_NUMERIC_QUADRATURE_KRONROD_COEFFICIENTS_HPP

#if defined(MSC_VER) && MSC_VER>1000
#pragma once
#endif

// Copyright (C) 2007 by Hugo Duncan

// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or
// copy at http://www.boost.org/LICENSE_1_0.txt)

/*!
  @file   kronrod_coefficients.hpp
  @brief  Coefficients for Kronrod integration formulae
*/

#include <boost/numeric/quadrature/quadrature_config.hpp>
#include <boost/tr1/array.hpp>

// taken from math toolkit
#define SC_(x) static_cast<T>(BOOST_JOIN(x, L))

namespace boost
{
  namespace numeric
  {
    namespace quadrature
    {
      //! Coefficients for kronrod intergration
      /*! Coefficients for N point kronrod intergration.  This class
        provides common syntax for refering to kronrod coefficients,
        but has no default implementation. Available specialisations
        are, kronrod_coefficents<T,15>, kronrod_coefficents<T,21>,
        kronrod_coefficents<T,31>, kronrod_coefficents<T,41>, and
        kronrod_coefficents<T,51>.
       */
      template <typename T, std::size_t N>
      struct kronrod_coefficients
#ifdef BOOST_QUADRATURE_DOXYGEN
      {
        typedef std::tr1::array<T,N/2+1> value_type;
        //! Weights for each integrand value
        static const value_type& weights();
        // Abscissa for evaluating the integrand
        static const value_type& abcissa();
      }
#endif
      ;

      //! Coefficients for 15 point kronrod intergration
      /*! Specialisation of kronrod_coefficients for 15 points
       */
      template <typename T>
      struct kronrod_coefficients<T,15>
      {
        typedef std::tr1::array<T,8> value_type;

        static const value_type& weights()
        {
          static const value_type w={
            SC_(0.022935322010529224963732008058970) ,
            SC_(0.063092092629978553290700663189204) ,
            SC_(0.104790010322250183839876322541518) ,
            SC_(0.140653259715525918745189590510238) ,
            SC_(0.169004726639267902826583426598550) ,
            SC_(0.190350578064785409913256402421014) ,
            SC_(0.204432940075298892414161999234649) ,
            SC_(0.209482141084727828012999174891714)
          };
          return w;
        }

        static const value_type& abcissa()
        {
          static const value_type x={
            SC_(0.991455371120812639206854697526329) ,
            SC_(0.949107912342758524526189684047851) ,
            SC_(0.864864423359769072789712788640926) ,
            SC_(0.741531185599394439863864773280788) ,
            SC_(0.586087235467691130294144838258730) ,
            SC_(0.405845151377397166906606412076961) ,
            SC_(0.207784955007898467600689403773245) ,
            SC_(0.000000000000000000000000000000000)
          };
          return x;
        }
      }
      ;

      template <typename T>
      struct kronrod_coefficients<T,21>
      {
        typedef std::tr1::array<T,11> value_type;

        static const value_type& weights()
        {
          static const value_type w={
            SC_(0.011694638867371874278064396062192),
            SC_(0.032558162307964727478818972459390),
            SC_(0.054755896574351996031381300244580),
            SC_(0.075039674810919952767043140916190),
            SC_(0.093125454583697605535065465083366),
            SC_(0.109387158802297641899210590325805),
            SC_(0.123491976262065851077958109831074),
            SC_(0.134709217311473325928054001771707),
            SC_(0.142775938577060080797094273138717),
            SC_(0.147739104901338491374841515972068),
            SC_(0.149445554002916905664936468389821)
          };
          return w;
        }

        static const value_type& abcissa()
        {
          static const value_type x={
            SC_(0.995657163025808080735527280689003),
            SC_(0.973906528517171720077964012084452),
            SC_(0.930157491355708226001207180059508),
            SC_(0.865063366688984510732096688423493),
            SC_(0.780817726586416897063717578345042),
            SC_(0.679409568299024406234327365114874),
            SC_(0.562757134668604683339000099272694),
            SC_(0.433395394129247190799265943165784),
            SC_(0.294392862701460198131126603103866),
            SC_(0.148874338981631210884826001129720),
            SC_(0.000000000000000000000000000000000)
          };
          return x;
        }
      }
      ;


      template <typename T>
      struct kronrod_coefficients<T,31>
      {
        typedef std::tr1::array<T,16> value_type;
        static const value_type& weights()
        {
          static const value_type w={
            SC_(0.005377479872923348987792051430128),
            SC_(0.015007947329316122538374763075807),
            SC_(0.025460847326715320186874001019653),
            SC_(0.035346360791375846222037948478360),
            SC_(0.044589751324764876608227299373280),
            SC_(0.053481524690928087265343147239430),
            SC_(0.062009567800670640285139230960803),
            SC_(0.069854121318728258709520077099147),
            SC_(0.076849680757720378894432777482659),
            SC_(0.083080502823133021038289247286104),
            SC_(0.088564443056211770647275443693774),
            SC_(0.093126598170825321225486872747346),
            SC_(0.096642726983623678505179907627589),
            SC_(0.099173598721791959332393173484603),
            SC_(0.100769845523875595044946662617570),
            SC_(0.101330007014791549017374792767493)
          };
          return w;
        }

        static const value_type& abcissa()
        {
          static const value_type x={
            SC_(0.998002298693397060285172840152271),
            SC_(0.987992518020485428489565718586613),
            SC_(0.967739075679139134257347978784337),
            SC_(0.937273392400705904307758947710209),
            SC_(0.897264532344081900882509656454496),
            SC_(0.848206583410427216200648320774217),
            SC_(0.790418501442465932967649294817947),
            SC_(0.724417731360170047416186054613938),
            SC_(0.650996741297416970533735895313275),
            SC_(0.570972172608538847537226737253911),
            SC_(0.485081863640239680693655740232351),
            SC_(0.394151347077563369897207370981045),
            SC_(0.299180007153168812166780024266389),
            SC_(0.201194093997434522300628303394596),
            SC_(0.101142066918717499027074231447392),
            SC_(0.000000000000000000000000000000000)
          };
          return x;
        }
      };


      template <typename T>
      struct kronrod_coefficients<T,41>
      {
        typedef std::tr1::array<T,21> value_type;
        static const value_type& weights()
        {
          static const value_type w={
            SC_(0.003073583718520531501218293246031),
            SC_(0.008600269855642942198661787950102),
            SC_(0.014626169256971252983787960308868),
            SC_(0.020388373461266523598010231432755),
            SC_(0.025882133604951158834505067096153),
            SC_(0.031287306777032798958543119323801),
            SC_(0.036600169758200798030557240707211),
            SC_(0.041668873327973686263788305936895),
            SC_(0.046434821867497674720231880926108),
            SC_(0.050944573923728691932707670050345),
            SC_(0.055195105348285994744832372419777),
            SC_(0.059111400880639572374967220648594),
            SC_(0.062653237554781168025870122174255),
            SC_(0.065834597133618422111563556969398),
            SC_(0.068648672928521619345623411885368),
            SC_(0.071054423553444068305790361723210),
            SC_(0.073030690332786667495189417658913),
            SC_(0.074582875400499188986581418362488),
            SC_(0.075704497684556674659542775376617),
            SC_(0.076377867672080736705502835038061),
            SC_(0.076600711917999656445049901530102)
          };
          return w;
        }

        static const value_type& abcissa()
        {
          static const value_type x={
            SC_(0.998859031588277663838315576545863),
            SC_(0.993128599185094924786122388471320),
            SC_(0.981507877450250259193342994720217),
            SC_(0.963971927277913791267666131197277),
            SC_(0.940822633831754753519982722212443),
            SC_(0.912234428251325905867752441203298),
            SC_(0.878276811252281976077442995113078),
            SC_(0.839116971822218823394529061701521),
            SC_(0.795041428837551198350638833272788),
            SC_(0.746331906460150792614305070355642),
            SC_(0.693237656334751384805490711845932),
            SC_(0.636053680726515025452836696226286),
            SC_(0.575140446819710315342946036586425),
            SC_(0.510867001950827098004364050955251),
            SC_(0.443593175238725103199992213492640),
            SC_(0.373706088715419560672548177024927),
            SC_(0.301627868114913004320555356858592),
            SC_(0.227785851141645078080496195368575),
            SC_(0.152605465240922675505220241022678),
            SC_(0.076526521133497333754640409398838),
            SC_(0.000000000000000000000000000000000)
          };
          return x;
        }
      };


      template <typename T>
      struct kronrod_coefficients<T,51>
      {
        typedef std::tr1::array<T,26> value_type;
        static const value_type& weights()
        {
          static const value_type w={
            SC_(0.001987383892330315926507851882843),
            SC_(0.005561932135356713758040236901066),
            SC_(0.009473973386174151607207710523655),
            SC_(0.013236229195571674813656405846976),
            SC_(0.016847817709128298231516667536336),
            SC_(0.020435371145882835456568292235939),
            SC_(0.024009945606953216220092489164881),
            SC_(0.027475317587851737802948455517811),
            SC_(0.030792300167387488891109020215229),
            SC_(0.034002130274329337836748795229551),
            SC_(0.037116271483415543560330625367620),
            SC_(0.040083825504032382074839284467076),
            SC_(0.042872845020170049476895792439495),
            SC_(0.045502913049921788909870584752660),
            SC_(0.047982537138836713906392255756915),
            SC_(0.050277679080715671963325259433440),
            SC_(0.052362885806407475864366712137873),
            SC_(0.054251129888545490144543370459876),
            SC_(0.055950811220412317308240686382747),
            SC_(0.057437116361567832853582693939506),
            SC_(0.058689680022394207961974175856788),
            SC_(0.059720340324174059979099291932562),
            SC_(0.060539455376045862945360267517565),
            SC_(0.061128509717053048305859030416293),
            SC_(0.061471189871425316661544131965264),
            SC_(0.061580818067832935078759824240066)
          };
          return w;
        }

        static const value_type& abcissa()
        {
          static const value_type x={
            SC_(0.999262104992609834193457486540341),
            SC_(0.995556969790498097908784946893902),
            SC_(0.988035794534077247637331014577406),
            SC_(0.976663921459517511498315386479594),
            SC_(0.961614986425842512418130033660167),
            SC_(0.942974571228974339414011169658471),
            SC_(0.920747115281701561746346084546331),
            SC_(0.894991997878275368851042006782805),
            SC_(0.865847065293275595448996969588340),
            SC_(0.833442628760834001421021108693570),
            SC_(0.797873797998500059410410904994307),
            SC_(0.759259263037357630577282865204361),
            SC_(0.717766406813084388186654079773298),
            SC_(0.673566368473468364485120633247622),
            SC_(0.626810099010317412788122681624518),
            SC_(0.577662930241222967723689841612654),
            SC_(0.526325284334719182599623778158010),
            SC_(0.473002731445714960522182115009192),
            SC_(0.417885382193037748851814394594572),
            SC_(0.361172305809387837735821730127641),
            SC_(0.303089538931107830167478909980339),
            SC_(0.243866883720988432045190362797452),
            SC_(0.183718939421048892015969888759528),
            SC_(0.122864692610710396387359818808037),
            SC_(0.061544483005685078886546392366797),
            SC_(0.000000000000000000000000000000000)
          };
          return x;
        }
      };
#undef SC_
    }// namespace
  }// namespace
}// namespace

#endif
